﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Microsoft Corp." file="RestServiceContext.cs">
//   All rights reserved. See License.txt in the project root for license information.
// </copyright>
// 
// --------------------------------------------------------------------------------------------------------------------
namespace RestClient
{
    using System;
    using System.Net;
    using System.Text;

    public abstract class RestServiceContext : IRestServiceContext
    {
        protected RestServiceContext(Uri serviceUri, IServiceCredentials serviceCredentials)
        {
            this.ServiceUri = serviceUri;
            this.ServiceCredentials = serviceCredentials;
        }

        public Uri ServiceUri { get; private set; }

        public IServiceCredentials ServiceCredentials { get; private set; }

        public virtual WebRequest BuildRequest(Func<RequestContext> requestContextFactory)
        {
            var requestContext = requestContextFactory();
            var webRequest = this.CreateWebRequest(requestContext);

            webRequest.Headers = requestContext.GetHeaderCollection();
            this.AddHeaders(webRequest);

            webRequest.Method = requestContext.Method.ToString();

            webRequest = this.ServiceCredentials.Sign(webRequest);
            webRequest.ContentLength = 0;
            if (!string.IsNullOrEmpty(requestContext.Body))
            {
                byte[] data = Encoding.UTF8.GetBytes(requestContext.Body);
                webRequest.ContentType = requestContext.ContentType;
                webRequest.ContentLength = data.Length;
                using (var stream = webRequest.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }

            return webRequest;
        }

        protected Uri BuildRequestUri(RequestContext requestContext)
        {
            var queryToAppend = requestContext.GetQueryString();

            if (queryToAppend.Length > 1)
            {
                queryToAppend = queryToAppend.Substring(1);
            }

            var baseUri = new UriBuilder(this.ServiceUri);

            if (!string.IsNullOrEmpty(requestContext.Path))
            {
                baseUri.Path += requestContext.Path;
            }

            baseUri.Query = (baseUri.Query.Length > 1)
                                ? baseUri.Query.Substring(1) + "&" + queryToAppend
                                : baseUri.Query = queryToAppend;

            return baseUri.Uri;
        }

        protected virtual WebRequest CreateWebRequest(RequestContext requestContext)
        {
            return WebRequest.Create(this.BuildRequestUri(requestContext));
        }

        protected virtual void AddHeaders(WebRequest request)
        {
        }
    }
}